package br.com.android.financas.repositorio.impl;

import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.PeriodType;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import br.com.android.financas.DiaBase;
import br.com.android.financas.MesTotal;
import br.com.android.financas.model.Apresentavel;
import br.com.android.financas.model.Poupanca;
import br.com.android.financas.repositorio.RepositorioGenerico;
import br.com.android.financas.repositorio.RepositorioPoupanca;

import com.j256.ormlite.dao.GenericRawResults;
import com.j256.ormlite.stmt.QueryBuilder;

public class RepositorioPoupancaImpl extends RepositorioGenerico<Poupanca> implements RepositorioPoupanca {
	private Context context;
	public RepositorioPoupancaImpl(Context context) throws SQLException {
		super(context);
		this.context=context;
	}

	private double getTotal(List<Poupanca> poupancas){
		double total=0;
		for(Poupanca poupanca:poupancas){
			total+=poupanca.getValor();
		}
		return total;
	}

	private double getTotalDespesa(List<Poupanca> poupancas){
		double total=0;
		for(Poupanca poupanca:poupancas){
			if(poupanca.isDespesa())
					total+=poupanca.getValor();
		}
		return total;
	}

	public double getTotal() {

		List<Poupanca> poupancas=listar();

		return getTotal(poupancas);
	}

	@Override
	public double getTotal(Date mes) {

		DateTime m=new DateTime(mes.getTime());

		DateTime ini=m.dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
		DateTime fim=m.dayOfMonth().withMaximumValue().withTimeAtStartOfDay();


		return getTotal(ini.toDate(), fim.toDate());
	}

	@Override
	public double getTotalDespesa(Date mes) {

		DateTime m=new DateTime(mes.getTime());

		DateTime ini=m.dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
		DateTime fim=m.dayOfMonth().withMaximumValue().withTimeAtStartOfDay();


		return getTotalDespesa(ini.toDate(), fim.toDate());
	}

	@Override
	public double getTotal(Date ini, Date fim) {

		try {

			GenericRawResults<String[]> rawResults= getDatabase().queryRaw("select sum(valor) from poupanca where date(data/1000,'unixepoch','localtime') between ? and ?", new SimpleDateFormat("yyyy-MM-dd").format(ini)  ,new SimpleDateFormat("yyyy-MM-dd").format(fim));
			return Double.parseDouble(rawResults.getFirstResult()[0]);

		} catch (Exception e) {
			return 0;
		}
	}

	@Override
	public double getTotalDespesa(Date ini, Date fim) {

		QueryBuilder<Poupanca, Integer> query = getDatabase().queryBuilder();
		try {
			List<Poupanca> poupancas=query.where().between("data", ini,fim).or().eq("data", ini).or().eq("data", fim).and().eq("despesa", true).query();

			return getTotalDespesa(poupancas);

		} catch (SQLException e) {

		}

		return 0;
	}

	@Override
	public List<DiaBase> getDiasBases() {

		Map<DiaBase,DiaBase> dias=new HashMap<DiaBase, DiaBase>();
		List<Poupanca> poupancas=listar();

		for(Poupanca poupanca:poupancas){

			DiaBase dia=new DiaBase();
			dia.setData((new DateTime(poupanca.getData().getTime())).withTimeAtStartOfDay().withTimeAtStartOfDay());

			if(!dias.containsKey(dia)){
				dia.getPoupancas().add(poupanca);
				dias.put(dia,dia);
			}else
			{
				dias.get(dia).getPoupancas().add(poupanca);
			}
		}

		List<DiaBase> tmp=new ArrayList<DiaBase>();

		for(DiaBase dia:dias.values()){
			tmp.add(dia);
		}
		return tmp;

	}

	@Override
	public Map<MesTotal, List<Apresentavel>> getDespesasMensais() {
		Map<MesTotal, List<Apresentavel>> meses=new LinkedHashMap<MesTotal, List<Apresentavel>>();
		List<Poupanca> poupancas=listar();

		Map<DateTime,MesTotal> mesesIncluidos=new HashMap<DateTime,MesTotal>();

		for(Poupanca poupanca:poupancas){

			DateTime tMes= (new DateTime(poupanca.getData().getTime())).dayOfMonth().withMinimumValue().withTimeAtStartOfDay();

			if(!mesesIncluidos.containsKey(tMes)){
				MesTotal mes= new MesTotal();
				mes.setMes(tMes);
				mes.setTotal(getTotalDespesa(tMes.toDate()));

				mesesIncluidos.put(tMes, mes);
				meses.put(mes, new ArrayList<Apresentavel>());
			}

			meses.get(mesesIncluidos.get(tMes)).add(poupanca);

		}

		return meses;
	}

	private List<Poupanca> getAtualizaveis(){
		QueryBuilder<Poupanca, Integer> query = getDatabase().queryBuilder();
		DateTime hoje=new DateTime().withTimeAtStartOfDay();
		List<Poupanca> tmp=listar();
		List<Poupanca> poupancas=new ArrayList<Poupanca>();

		for(Poupanca poupanca:tmp){
			if(poupanca.getAtualizado()==null || !poupanca.getAtualizado().equals(hoje.toDate())){
				if(poupanca.getData().getDate()==hoje.getDayOfMonth()){
					Period p = new Period(new DateTime(poupanca.getData()), hoje, PeriodType.months().withDaysRemoved());
					int qtd = p.getMonths();
					if(qtd>=1){
						poupancas.add(poupanca);
					}
				}
			}
		}

		return poupancas;
	}

	@Override
	public void atualizaPorJuros() {

		SharedPreferences preference = PreferenceManager.getDefaultSharedPreferences(context);

		double taxa= Double.parseDouble(preference.getString("taxaJuros", "0"));
		Log.e("TAXA JUROS", Double.toString(taxa));
		if(taxa>0){
			List<Poupanca> poupancas=getAtualizaveis();

			for(Poupanca poupanca:poupancas){
				double valor=poupanca.getValor();
				valor=valor+((valor*taxa)/100);
				poupanca.setValor(valor);
				poupanca.setAtualizado(new DateTime().withTimeAtStartOfDay().toDate());
				try {
					atualizar(poupanca);
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@Override
	public List<MesTotal> getTotaisMensais() {

		try {
			List<MesTotal> totais=new ArrayList<MesTotal>();
			GenericRawResults<String[]> rawResults= getDatabase().queryRaw("select data,sum(valor) from poupanca where despesa=1 group by strftime('%Y-%m',date(data/1000,'unixepoch','localtime'))");

			for (String[] resultArray : rawResults) {
				MesTotal mes= new MesTotal();
				try {
					DateTime data=new DateTime( new SimpleDateFormat("yyyy-MM-dd").parse(resultArray[0].split("\\.")[0]).getTime());
					data=data.dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
					mes.setMes(data);
					mes.setTotal(Double.parseDouble(resultArray[1]) );
					totais.add(mes);
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
			rawResults.close();
			return totais;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return Collections.emptyList();
	}

	@Override
	public List<Poupanca> getDespesas(Date mes) {
		DateTime m = new DateTime(mes.getTime());

		DateTime ini = m.dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
		DateTime fim = m.dayOfMonth().withMaximumValue().withTimeAtStartOfDay();

		return getDespesas(ini.toDate(), fim.toDate());
	}

	@Override
	public List<Poupanca> getDespesas(Date ini, Date fim) {

		try {
			return  getDatabase().queryBuilder().where().between("data", ini, fim).or().eq("data", ini).or().eq("data", fim).query();
		} catch (SQLException e1) {}
		return Collections.emptyList();
	}
}
